package com.angcyo.selenium.auto.action

import com.angcyo.javafx.base.ex.onBack
import com.angcyo.javafx.ui.*
import com.angcyo.library.file.fileName
import com.angcyo.selenium.PairOutputType
import com.angcyo.selenium.auto.BaseControl
import com.angcyo.selenium.auto.isValidElement
import com.angcyo.selenium.auto.parse.HandleResult
import com.angcyo.selenium.auto.toStr
import com.angcyo.selenium.bean.ActionBean
import com.angcyo.selenium.bean.putMap
import com.angcyo.selenium.isValid
import com.angcyo.selenium.js.exeJs
import javafx.scene.image.Image
import javafx.stage.Screen
import org.openqa.selenium.Rectangle
import org.openqa.selenium.WebElement
import org.openqa.selenium.remote.RemoteWebDriver

/**
 * Email:angcyo@126.com
 * @author angcyo
 * @date 2021/01/12
 */
class ScreenshotAction : BaseAction() {

    companion object {
        var screenshotAction: ((screenshot: Image?, clipImage1: Image?, clipImage2: Image?) -> Unit)? = null
    }

    override fun interceptAction(control: BaseControl, action: String?): Boolean {
        return action?.startsWith(Action.ACTION_SCREENSHOT) == true ||
                action?.startsWith(Action.ACTION_SHOT) == true
    }

    override fun runAction(
        control: BaseControl,
        element: WebElement,
        actionBean: ActionBean,
        action: String
    ): HandleResult {
        val result = HandleResult()
        result.elementList = listOf(element)

        //解析参数
        val key = action.arg("key") ?: "imageCode"
        val css = action.arg("css")

        //剪切的矩形
        var clipRect: Rectangle? = null
        val rectangle = control._autoParse.valueParse.parseRect(action, control._autoParse.getBounds())
        if (rectangle?.isValid() == true) {
            clipRect = rectangle
        } else {
            if (element.isValidElement()) {
                clipRect = element.rect
            }
        }

        //开始截图
        (control.driver as? RemoteWebDriver)?.getScreenshotAs(PairOutputType())?.let { pair ->
            val image = if (clipRect == null) {
                //不需要裁剪
                pair.second
            } else {
                //需要裁剪
                fun clip(): Image? {
                    val scaleX = Screen.getPrimary().outputScaleX
                    val scaleY = Screen.getPrimary().outputScaleY

                    val x = clipRect.x * scaleX
                    val y = clipRect.y * scaleY

                    val width = clipRect.width * scaleX
                    val height = clipRect.height * scaleY

                    if (x + width > pair.second.width || y + height > pair.second.height) {
                        return null
                    }
                    return pair.second.clipRect(x.toInt(), y.toInt(), width.toInt(), height.toInt())
                }

                //第一次切
                val clipImage1 = clip()
                clipImage1 ?: if (css.isNullOrEmpty()) {
                    null
                } else {
                    //如果目标的位置在截图外面
                    val exeJsResult = (control.driver as? RemoteWebDriver)?.exeJs("get_element_bounds.js", css)
                    control.logAction?.invoke("执行js返回:${exeJsResult}")
                    exeJsResult?.run {
                        if (this is List<*>) {
                            if (this.size == 4) {
                                //通过js 获取元素坐标, 然后截取对应位置的图片
                                val left = this[0]?.toString()?.toFloatOrNull()?.toInt() ?: -1
                                val top = this[1]?.toString()?.toFloatOrNull()?.toInt() ?: -1
                                val width = this[2]?.toString()?.toFloatOrNull()?.toInt() ?: -1
                                val height = this[3]?.toString()?.toFloatOrNull()?.toInt() ?: -1

                                if (left > 0 && top > 0 && width > 0 && height > 0) {
                                    clipRect.setX(left)
                                    clipRect.setY(top)
                                    clipRect.setWidth(width)
                                    clipRect.setHeight(height)
                                    //第二次切
                                    clip()
                                } else {
                                    null
                                }
                            } else {
                                null
                            }
                        } else {
                            null
                        }
                    }
                }
            }

            //处理剪切之后的图片
            image?.let {
                //保存验证码图片
                onBack {
                    screenshotAction?.invoke(
                        image,
                        pair.second,
                        image.toByteArray().toImage(image.width.toInt(), image.height.toInt()),
                    )
                    PairOutputType().apply {
                        fileName = fileName(suffix = "_${key}.png")
                        image.saveToFile(getSaveFile())
                    }
                }

                try {
                    val base64 = image.toBufferedImage()?.toByteArray()?.toBase64()
                    result.success = base64 != null
                    //保存起来
                    control._currentTaskBean?.putMap(key, base64)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }

            //end
        }

        control.logAction?.invoke("获取截图clip[${clipRect?.toStr()}]:${result.success}")
        return result
    }
}